#include "cipher.hpp"
#include <openssl/pem.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/core_names.h>
#include <openssl/param_build.h>
#include "loger.hpp"

static constexpr size_t        SM2_PRV_LEN = 32;
static constexpr size_t        SM2_PUC_LEN = 64;
static constexpr unsigned char id[]        = "1234567812345678";

std::vector<sl::byte> sl::str2bin(const std::string& str)
{
    std::vector<sl::byte> result;

    // 确保输入字符串长度为偶数（每两个字符表示一个字节）
    if(str.length() % 2 != 0) {
        throw std::invalid_argument("Hex string must have even length");
    }

    // 遍历字符串，每两个字符转换为一个字节
    for(size_t i = 0; i < str.length(); i += 2) {
        // 提取两个字符
        std::string byteStr = str.substr(i, 2);

        // 将十六进制字符串转换为整数
        sl::byte byteValue =
            static_cast<sl::byte>(std::stoi(byteStr, nullptr, 16));

        // 添加到结果中
        result.push_back(byteValue);
    }

    return result;
}

static bool puc_strip(std::vector<sl::byte>& puc)
{
    size_t puc_len = puc.size();
    if(puc_len == (SM2_PUC_LEN + 1) && puc[0] == 0x04) {
        // 包含前导字节0x04的未压缩格式, 删除
        puc.erase(puc.begin());
        puc_len--;
        puc.resize(puc_len);
        return true;
    } else if(puc_len != SM2_PUC_LEN) {
        sl::loger::error("Unexpected public key format, length: {}", puc_len);
        return false;
    }
    return true;
}

static void puc_unstrip(std::vector<sl::byte>& puc)
{
    size_t puc_len = puc.size();
    if(puc_len == SM2_PUC_LEN) {
        puc.insert(puc.begin(), 0x04);
    }
}

/**
 * @brief 生成SM2椭圆曲线密钥对
 *
 * 该函数使用OpenSSL库生成SM2椭圆曲线算法的密钥对，包括私钥和公钥。
 * 私钥和公钥分别存储在传入的vector参数中。
 *
 * @param prv[out] 存储生成的私钥数据，函数会调整其大小并填充私钥内容- 32字节
 * @param puc[out] 存储生成的公钥数据，函数会调整其大小并填充公钥内容- 64字节
 * @return bool 成功生成密钥对返回true，否则返回false
 */
bool sl::ecc_generate(std::vector<sl::byte>& prv, std::vector<byte>& puc)
{
    prv.resize(128);
    puc.resize(128);

    // 生成SM2密钥对
    EVP_PKEY* pkey = EVP_EC_gen(SN_sm2);
    if(pkey == nullptr) {
        sl::loger::error("Failed to generate SM2 key pair");
        return false;
    }
    defer([pkey]() { EVP_PKEY_free(pkey); });

    // 提取公钥数据
    size_t puc_len = puc.size();
    if(1 != EVP_PKEY_get_octet_string_param(
                pkey, OSSL_PKEY_PARAM_PUB_KEY, puc.data(), puc_len, &puc_len)) {
        sl::loger::error("Failed to get public key");
        return false;
    }
    puc.resize(puc_len);

    // 提取私钥数据
    BIGNUM* prv_bn = nullptr;
    if(1 != EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &prv_bn)) {
        sl::loger::error("Failed to get private key number");
        return false;
    }
    defer([prv_bn]() { BN_free(prv_bn); });

    // 将私钥大数转换为二进制格式并调整缓冲区大小
    BN_bn2bin(prv_bn, prv.data());
    prv.resize(BN_num_bytes(prv_bn));

    return puc_strip(puc);
}

/**
 * @brief 从指定路径读取SM2私钥文件，并提取32字节的私钥数据
 *
 * 该函数打开PEM格式的私钥文件，解析其中的ECC私钥，并将其转换为32字节的二进制数据。
 * 支持OpenSSL 3.0及以上版本的API。
 *
 * @param path 私钥文件的路径
 * @return std::vector<sl::byte> 包含32字节私钥数据的向量，失败时返回空向量
 */
std::vector<sl::byte> sl::read_private(const std::string& path)
{
    FILE* fp = fopen(path.c_str(), "r");
    if(!fp) {
        sl::loger::error("Failed to open private key file: " + path);
        return {};
    }
    defer([fp]() { fclose(fp); });

    // // 读取PEM格式的私钥
    EVP_PKEY* pkey = PEM_read_PrivateKey(fp, nullptr, nullptr, nullptr);
    if(!pkey) {
        sl::loger::error("Failed to parse private key: " + path);
        return {};
    }
    defer([pkey]() { EVP_PKEY_free(pkey); });

    // 验证私钥类型是否为EC密钥（SM2基于EC）
    if(EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) {
        sl::loger::error("Key is not an EC key: " + path);
        return {};
    }

    // 使用OpenSSL 3.0 API获取私钥的大数表示
    BIGNUM* priv_bn = nullptr;
    if(EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &priv_bn) != 1) {
        sl::loger::error("Failed to get private key number: " + path);
        return {};
    }
    defer([priv_bn]() { BN_free(priv_bn); });

    // 将大数形式的私钥转换为32字节的二进制数据
    std::vector<sl::byte> priv_data(BN_num_bytes(priv_bn));
    int                   len = BN_bn2bin(priv_bn, priv_data.data());
    if(len != SM2_PRV_LEN) {
        sl::loger::error("Failed to convert private key to 32 bytes: " + path);
        return {};
    }
    return priv_data;
}

/**
 * @brief 读取并解析公钥文件
 * @param path 公钥文件路径
 * @return 返回解析后的公钥数据，失败时返回空vector
 */
std::vector<sl::byte> sl::read_public(const std::string& path)
{
    FILE* fp = fopen(path.c_str(), "r");
    if(!fp) {
        sl::loger::error("Failed to open public key file: " + path);
        return {};
    }
    defer([fp]() { fclose(fp); });
    // // 读取PEM格式的公钥
    EVP_PKEY* pkey = PEM_read_PUBKEY(fp, nullptr, nullptr, nullptr);
    if(!pkey) {
        sl::loger::error("Failed to parse public key: " + path);
        return {};
    }
    defer([pkey]() { EVP_PKEY_free(pkey); });

    std::vector<sl::byte> puc(128);
    size_t                puc_len = puc.size();
    // 使用OpenSSL 3.0 API获取公钥的二进制数据
    if(EVP_PKEY_get_octet_string_param(
           pkey, OSSL_PKEY_PARAM_PUB_KEY, puc.data(), puc_len, &puc_len) != 1) {
        sl::loger::error("Failed to get public key data: " + path);
        return {};
    }
    puc.resize(puc_len);

    // 清理公钥数据中的填充信息
    if(puc_strip(puc) == false) {
        return {};
    }
    return puc;
}

std::vector<sl::byte> sl::calculate_hash(const std::vector<byte>& data)
{
    EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
    if(!mdctx) {
        sl::loger::error("Failed to create EVP_MD_CTX");
        return {};
    }
    defer([mdctx]() { EVP_MD_CTX_free(mdctx); });

    const EVP_MD* md = EVP_sm3();
    if(!md) {
        sl::loger::error("Failed to get SM3 digest");
        return {};
    }

    if(EVP_DigestInit_ex(mdctx, md, nullptr) != 1) {
        sl::loger::error("Failed to initialize SM3 digest");
        return {};
    }

    if(EVP_DigestUpdate(mdctx, data.data(), data.size()) != 1) {
        sl::loger::error("Failed to update SM3 digest");
        return {};
    }

    std::vector<sl::byte> hash(EVP_MD_size(md));
    unsigned int          hash_len = hash.size();

    if(EVP_DigestFinal_ex(mdctx, hash.data(), &hash_len) != 1) {
        sl::loger::error("Failed to finalize SM3 digest");
        return {};
    }

    hash.resize(hash_len);
    return hash;
}

/**
 * @brief 根据SM2私钥计算对应的公钥（PUC）
 *
 * 该函数使用SM2椭圆曲线算法，根据输入的私钥计算出对应的公钥。
 * 公钥以未压缩格式返回。
 *
 * @param prv 输入的SM2私钥，字节序列形式
 * @return 返回计算出的公钥，失败时返回空vector
 */
std::vector<sl::byte> sl::calculate_puc(const std::vector<byte>& prv)
{
    EC_GROUP*             group   = nullptr;
    EC_POINT*             puc_key = nullptr;
    std::vector<sl::byte> puc(128);
    size_t                puc_len = puc.size();

    // 将输入的私钥数据转换为BIGNUM结构，用于后续椭圆曲线运算
    BIGNUM* prv_bn = BN_bin2bn(prv.data(), prv.size(), NULL);
    if(prv_bn == nullptr) {
        sl::loger::error("Failed to convert private key to BIGNUM");
        return {};
    }
    defer([prv_bn]() { BN_free(prv_bn); });

    // 创建SM2椭圆曲线群结构
    group = EC_GROUP_new_by_curve_name(NID_sm2);
    if(group == nullptr) {
        sl::loger::error("Failed to create EC group");
        return {};
    }
    defer([group]() { EC_GROUP_free(group); });

    // 创建椭圆曲线上的点，用于存储计算出的公钥点
    puc_key = EC_POINT_new(group);
    if(puc_key == nullptr) {
        sl::loger::error("Failed to create EC point");
        return {};
    }
    defer([puc_key]() { EC_POINT_free(puc_key); });

    // 执行椭圆曲线点乘运算：pub_key = prv_bn * G（G为基点）
    EC_POINT_mul(group, puc_key, prv_bn, NULL, NULL, NULL);
    // 获取公钥点的未压缩格式字节长度
    puc_len = EC_POINT_point2oct(
        group, puc_key, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
    if(puc_len == 0) {
        sl::loger::error("Failed to calculate public key");
        return {};
    }
    // 将公钥点转换为未压缩格式的字节序列
    if(0 == EC_POINT_point2oct(group, puc_key, POINT_CONVERSION_UNCOMPRESSED,
                puc.data(), puc_len, NULL)) {
        sl::loger::error("Failed to convert public key to octet string");
        return {};
    }
    puc.resize(puc_len);
    // 对公钥进行格式处理（去除可能的冗余信息）
    if(puc_strip(puc) == false) {
        return {};
    }
    return puc;
}

/**
 * @brief 从私钥数据构造EVP_PKEY结构体指针
 *
 * 该函数将输入的SM2私钥数据转换为OpenSSL的EVP_PKEY结构体，用于后续的密码学操作。
 * 函数内部会根据私钥计算对应的公钥，并设置相关参数以构建完整的密钥对。
 *
 * @param prv 私钥数据，以字节向量形式表示
 * @return 返回指向EVP_PKEY结构体的指针；如果失败则返回nullptr
 */
static EVP_PKEY* pkey_from_prv(const std::vector<sl::byte>& prv)
{
    // 创建参数构建器
    OSSL_PARAM_BLD* bld = OSSL_PARAM_BLD_new();
    if(bld == nullptr) {
        sl::loger::error("Failed to create OSSL_PARAM_BLD");
        return nullptr;
    }
    sl::defer([bld]() { OSSL_PARAM_BLD_free(bld); });

    // 将私钥数据转换为BIGNUM格式
    BIGNUM* prv_bn = BN_bin2bn(prv.data(), prv.size(), NULL);
    if(prv_bn == nullptr) {
        sl::loger::error("Failed to convert private key to BIGNUM");
        return nullptr;
    }
    sl::defer([prv_bn]() { BN_free(prv_bn); });

    // 添加私钥参数
    OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, prv_bn);
    // 根据私钥计算公钥
    std::vector<sl::byte> puc = sl::calculate_puc(prv);
    if(puc.empty()) {
        sl::loger::error("Failed to calculate public key");
        return nullptr;
    }
    puc_unstrip(puc);

    // 添加公钥和算法组参数
    OSSL_PARAM_BLD_push_octet_string(
        bld, OSSL_PKEY_PARAM_PUB_KEY, puc.data(), puc.size());
    OSSL_PARAM_BLD_push_utf8_string(bld, "group", SN_sm2, 0);

    // 构建最终参数列表
    OSSL_PARAM* params = OSSL_PARAM_BLD_to_param(bld);
    if(params == nullptr) {
        sl::loger::error("Failed to build OSSL_PARAM");
        return nullptr;
    }
    sl::defer([params]() { OSSL_PARAM_free(params); });

    // 初始化并填充EVP_PKEY结构体
    EVP_PKEY*     pkey = nullptr;
    EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, SN_sm2, NULL);
    if(pctx == nullptr) {
        sl::loger::error("Failed to create EVP_PKEY_CTX");
        return nullptr;
    }
    EVP_PKEY_fromdata_init(pctx);
    EVP_PKEY_fromdata(pctx, &pkey, EVP_PKEY_KEYPAIR, params);
    EVP_PKEY_CTX_free(pctx);

    return pkey;
}

/**
 * @brief 从公钥数据创建EVP_PKEY对象
 *
 * 该函数使用SM2算法将公钥数据转换为EVP_PKEY结构体，
 * 用于后续的密码学操作。
 *
 * @param puc 包含公钥数据的字节向量
 * @return EVP_PKEY* 成功时返回指向EVP_PKEY的指针，失败时返回nullptr
 */
static EVP_PKEY* pkey_from_puc(const std::vector<sl::byte>& puc)
{
    // 创建参数构建器
    OSSL_PARAM_BLD* bld = OSSL_PARAM_BLD_new();
    if(bld == nullptr) {
        sl::loger::error("Failed to create OSSL_PARAM_BLD");
        return nullptr;
    }
    sl::defer([bld]() { OSSL_PARAM_BLD_free(bld); });

    // 设置公钥参数和SM2算法组
    OSSL_PARAM_BLD_push_octet_string(
        bld, OSSL_PKEY_PARAM_PUB_KEY, puc.data(), puc.size());
    OSSL_PARAM_BLD_push_utf8_string(bld, "group", SN_sm2, 0);
    OSSL_PARAM* params = OSSL_PARAM_BLD_to_param(bld);
    if(params == nullptr) {
        sl::loger::error("Failed to build OSSL_PARAM");
        return nullptr;
    }
    sl::defer([params]() { OSSL_PARAM_free(params); });

    // 创建SM2算法上下文并生成公钥对象
    EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, SN_sm2, NULL);
    if(pctx == nullptr) {
        sl::loger::error("Failed to create EVP_PKEY_CTX");
        return nullptr;
    }
    sl::defer([pctx]() { EVP_PKEY_CTX_free(pctx); });

    if(1 != EVP_PKEY_fromdata_init(pctx)) {
        sl::loger::error("Failed to initialize EVP_PKEY_CTX");
        return nullptr;
    }

    EVP_PKEY* pkey = nullptr;
    if(1 != EVP_PKEY_fromdata(pctx, &pkey, EVP_PKEY_PUBLIC_KEY, params)) {
        sl::loger::error("Failed to generate EVP_PKEY");
        return nullptr;
    }

    return pkey;
}

/**
 * @brief 将DER编码的ECDSA签名转换为RS格式签名
 *
 * 该函数解析DER格式的ECDSA签名，并将其转换为64字节的RS格式签名，
 * 其中前32字节为r值，后32字节为s值。
 *
 * @param sign DER编码的ECDSA签名数据
 * @return std::vector<sl::byte> RS格式的签名数据，长度为64字节；
 *         转换失败时返回空vector
 */
std::vector<sl::byte> sign_to_rs(const std::vector<sl::byte>& sign)
{
    const sl::byte* der_data = sign.data();
    ECDSA_SIG*      sig      = d2i_ECDSA_SIG(nullptr, &der_data, sign.size());
    if(sig == nullptr) {
        sl::loger::error("Failed to parse DER signature");
        return {};
    }
    sl::defer([sig]() { ECDSA_SIG_free(sig); });

    const BIGNUM* r = nullptr;
    const BIGNUM* s = nullptr;
    ECDSA_SIG_get0(sig, &r, &s);

    std::vector<sl::byte> rs(SM2_PUC_LEN, 0); // 32字节r + 32字节s

    // 提取r值（前32字节）
    // if(BN_num_bytes(r) != SM2_PRV_LEN) {
    //     sl::loger::error("r value too long:{}", BN_num_bytes(r));
    //     return {};
    // }
    BN_bn2binpad(r, rs.data(), SM2_PRV_LEN);

    // 提取s值（后32字节）
    // if(BN_num_bytes(s) != SM2_PRV_LEN) {
    //     sl::loger::error("s value too long:{}", BN_num_bytes(r));
    //     return {};
    // }
    BN_bn2binpad(s, rs.data() + SM2_PRV_LEN, SM2_PRV_LEN);

    return rs;
}

/**
 * @brief 将原始签名格式转换为DER编码格式的签名
 *
 * 该函数接收64字节的原始签名数据（前32字节为r值，后32字节为s值），
 * 并将其转换为DER编码格式的ECDSA签名。
 *
 * @param rs 64字节的原始签名数据，前32字节为r值，后32字节为s值
 * @return std::vector<sl::byte> DER编码格式的签名数据，转换失败时返回空vector
 */
std::vector<sl::byte> rs_to_sign(const std::vector<sl::byte>& rs)
{
    if(rs.size() != 64) {
        sl::loger::error("Raw signature must be 64 bytes");
        return {};
    }

    BIGNUM* r = BN_bin2bn(rs.data(), SM2_PRV_LEN, nullptr);
    BIGNUM* s = BN_bin2bn(rs.data() + SM2_PRV_LEN, SM2_PRV_LEN, nullptr);
    // sl::defer([r, s]() {
    //     BN_free(r); BN_free(s);
    // });

    ECDSA_SIG* sig = ECDSA_SIG_new();
    if(sig == nullptr) {
        sl::loger::error("Failed to create ECDSA_SIG");
        return {};
    }
    sl::defer([sig]() { ECDSA_SIG_free(sig); });

    if(ECDSA_SIG_set0(sig, r, s) == 0) {
        sl::loger::error("Failed to set signature components");
        return {};
    }
    // 注意：ECDSA_SIG_set0会接管r和s的内存管理，所以不需要手动释放

    unsigned char* der_data = nullptr;
    int            der_len  = i2d_ECDSA_SIG(sig, &der_data);
    if(der_len <= 32 || der_data == nullptr) {
        sl::loger::error("Failed to encode signature to DER");
        return {};
    }

    std::vector<sl::byte> sign(der_data, der_data + der_len);
    OPENSSL_free(der_data);

    return sign;
}

std::vector<sl::byte> sl::ecc_sign(
    const std::vector<byte>& data, const std::vector<byte>& prv)
{
    std::vector<sl::byte> sig(128);
    size_t                sig_len = sig.size();

    EVP_PKEY* pkey = pkey_from_prv(prv);
    if(pkey == nullptr) {
        sl::loger::error("Failed to create EVP_PKEY");
        return {};
    }
    sl::defer([pkey]() { EVP_PKEY_free(pkey); });

    EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new(pkey, NULL);
    if(pctx == nullptr) {
        sl::loger::error("Failed to create EVP_PKEY_CTX");
        return {};
    }
    defer([pctx]() { EVP_PKEY_CTX_free(pctx); });

    EVP_MD_CTX* mctx = EVP_MD_CTX_new();
    if(mctx == nullptr) {
        sl::loger::error("Failed to create EVP_MD_CTX");
        return {};
    }
    defer([mctx]() { EVP_MD_CTX_free(mctx); });

    EVP_PKEY_CTX_set1_id(pctx, id, 16);
    EVP_MD_CTX_set_pkey_ctx(mctx, pctx);
    EVP_DigestSignInit(mctx, NULL, EVP_sm3(), NULL, pkey);
    EVP_DigestSignUpdate(mctx, data.data(), data.size());
    EVP_DigestSignFinal(mctx, sig.data(), &sig_len);

    sig.resize(sig_len);
    return sign_to_rs(sig);
}

bool sl::ecc_verify(const std::vector<byte>& data, const std::vector<byte>& rs,
    const std::vector<byte>& puc)
{
    std::vector<byte> sign        = rs_to_sign(rs);
    std::vector<byte> unstrip_puc = puc;
    puc_unstrip(unstrip_puc);

    EVP_PKEY* pkey = pkey_from_puc(unstrip_puc);
    if(pkey == nullptr) {
        sl::loger::error("Failed to create EVP_PKEY");
        return false;
    }
    defer([pkey]() { EVP_PKEY_free(pkey); });

    EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new(pkey, NULL);
    if(pctx == nullptr) {
        sl::loger::error("Failed to create EVP_PKEY_CTX");
        return false;
    }
    defer([pctx]() { EVP_PKEY_CTX_free(pctx); });

    EVP_MD_CTX* mctx = EVP_MD_CTX_new();
    if(mctx == nullptr) {
        sl::loger::error("Failed to create EVP_MD_CTX");
        return false;
    }
    defer([mctx]() { EVP_MD_CTX_free(mctx); });

    EVP_PKEY_CTX_set1_id(pctx, id, 16);
    EVP_MD_CTX_set_pkey_ctx(mctx, pctx);
    EVP_DigestVerifyInit(mctx, NULL, EVP_sm3(), NULL, pkey);
    EVP_DigestVerifyUpdate(mctx, data.data(), data.size());
    return (1 == EVP_DigestVerifyFinal(mctx, sign.data(), sign.size()));
}

// ----------------------------------------------------
#include "openssl/asn1.h"
#include "openssl/asn1t.h"

typedef struct sm2_cipher_st {
    BIGNUM*            x_coordinate;
    BIGNUM*            y_coordinate;
    ASN1_OCTET_STRING* hash;
    ASN1_OCTET_STRING* cipher_text;
} SM2_CIPHER;
DECLARE_ASN1_FUNCTIONS(SM2_CIPHER)
ASN1_SEQUENCE(SM2_CIPHER) = {
    ASN1_SIMPLE(SM2_CIPHER, x_coordinate, BIGNUM),
    ASN1_SIMPLE(SM2_CIPHER, y_coordinate, BIGNUM),
    ASN1_SIMPLE(SM2_CIPHER, hash, ASN1_OCTET_STRING),
    ASN1_SIMPLE(SM2_CIPHER, cipher_text, ASN1_OCTET_STRING),
} ASN1_SEQUENCE_END(SM2_CIPHER) IMPLEMENT_ASN1_FUNCTIONS(SM2_CIPHER);

static std::vector<sl::byte> ecc_cipher2c1c3c2(
    const std::vector<sl::byte>& cipher)
{
    const unsigned char* p   = const_cast<unsigned char*>(cipher.data());
    SM2_CIPHER*          seq = d2i_SM2_CIPHER(NULL, &p, cipher.size());
    if(seq == nullptr) {
        sl::loger::error("Failed to decode SM2_CIPHER");
        return {};
    }
    sl::defer([seq]() { SM2_CIPHER_free(seq); });

    size_t olen = SM2_PUC_LEN + SM2_PRV_LEN + seq->cipher_text->length;
    std::vector<sl::byte> out(olen);
    unsigned char*        c = out.data();

    BN_bn2binpad(seq->x_coordinate, c, SM2_PRV_LEN);
    c += SM2_PRV_LEN;
    BN_bn2binpad(seq->y_coordinate, c, SM2_PRV_LEN);
    c += SM2_PRV_LEN;
    memcpy(c, seq->hash->data, SM2_PRV_LEN);
    c += SM2_PRV_LEN;
    memcpy(c, seq->cipher_text->data, seq->cipher_text->length);

    return out;
}

static std::vector<sl::byte> ecc_c1c3c2cipher(const std::vector<sl::byte>& ccc)
{
    if(ccc.size() < SM2_PUC_LEN + SM2_PRV_LEN) {
        sl::loger::error("Invalid C1C3C2 cipher format: data too short");
        return {};
    }

    // 创建SM2_CIPHER结构
    SM2_CIPHER* seq = SM2_CIPHER_new();
    if(seq == nullptr) {
        sl::loger::error("Failed to create SM2_CIPHER");
        return {};
    }
    sl::defer([seq]() { SM2_CIPHER_free(seq); });

    // 从输入数据中提取x坐标（前32字节）
    if(BN_bin2bn(ccc.data(), SM2_PRV_LEN, seq->x_coordinate) == nullptr) {
        sl::loger::error("Failed to convert x coordinate");
        return {};
    }
    // 从输入数据中提取y坐标（接下来的32字节）
    if(BN_bin2bn(ccc.data() + SM2_PRV_LEN, SM2_PRV_LEN, seq->y_coordinate) ==
        nullptr) {
        sl::loger::error("Failed to convert y coordinate");
        return {};
    }

    // 从输入数据中提取hash（接下来的32字节）
    if(ASN1_OCTET_STRING_set(
           seq->hash, ccc.data() + SM2_PUC_LEN, SM2_PRV_LEN) == 0) {
        sl::loger::error("Failed to set hash data");
        return {};
    }

    // cipher_text是剩余的数据部分
    size_t clen = ccc.size() - SM2_PUC_LEN - SM2_PRV_LEN;
    if(ASN1_OCTET_STRING_set(seq->cipher_text,
           ccc.data() + SM2_PUC_LEN + SM2_PRV_LEN, clen) == 0) {
        sl::loger::error("Failed to set cipher text data");
        return {};
    }

    // 编码为ASN.1 DER格式
    unsigned char* der_data = nullptr;
    int            der_len  = i2d_SM2_CIPHER(seq, &der_data);
    if(der_len <= 0 || der_data == nullptr) {
        sl::loger::error("Failed to encode SM2_CIPHER to DER format");
        return {};
    }
    sl::defer([der_data]() { OPENSSL_free(der_data); });

    // 将结果转换为vector
    std::vector<sl::byte> out(der_data, der_data + der_len);
    return out;
}

std::vector<sl::byte> sl::ecc_encrypt(
    const std::vector<byte>& data, const std::vector<byte>& puc)
{
    std::vector<byte> unstrip_puc = puc;
    puc_unstrip(unstrip_puc);

    EVP_PKEY* pkey = pkey_from_puc(unstrip_puc);
    if(pkey == nullptr) {
        sl::loger::error("Failed to create EVP_PKEY");
        return {};
    }
    defer([pkey]() { EVP_PKEY_free(pkey); });

    EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey, NULL);
    if(ctx == nullptr) {
        sl::loger::error("Failed to create EVP_PKEY_CTX");
        return {};
    }
    defer([ctx]() { EVP_PKEY_CTX_free(ctx); });

    size_t olen = 0;
    EVP_PKEY_encrypt_init(ctx);
    EVP_PKEY_encrypt(ctx, nullptr, &olen, data.data(), data.size());
    std::vector<sl::byte> out(olen);
    EVP_PKEY_encrypt(ctx, out.data(), &olen, data.data(), data.size());

    return ecc_cipher2c1c3c2(out);
}

std::vector<sl::byte> sl::ecc_decrypt(
    const std::vector<byte>& cipher, const std::vector<byte>& prv)
{
    std::vector<byte> data = ecc_c1c3c2cipher(cipher);
    EVP_PKEY*         pkey = pkey_from_prv(prv);
    if(pkey == nullptr) {
        sl::loger::error("Failed to create EVP_PKEY");
        return {};
    }
    defer([pkey]() { EVP_PKEY_free(pkey); });

    EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey, NULL);
    if(ctx == nullptr) {
        sl::loger::error("Failed to create EVP_PKEY_CTX");
        return {};
    }
    defer([ctx]() { EVP_PKEY_CTX_free(ctx); });

    size_t                olen = data.size();
    std::vector<sl::byte> out(olen);
    EVP_PKEY_decrypt_init(ctx);
    EVP_PKEY_decrypt(ctx, out.data(), &olen, data.data(), data.size());
    out.resize(olen);

    return out;
}

// ----------------------------------------------------
std::vector<sl::byte> sl::sym_encrypt(
    const std::vector<byte>& data, const std::vector<byte>& key)
{
    // 检查密钥长度是否为16字节（SM4要求）
    if(key.size() != 16) {
        sl::loger::error("SM4 key must be 16 bytes");
        return {};
    }

    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
    if(!ctx) {
        sl::loger::error("Failed to create EVP_CIPHER_CTX");
        return {};
    }
    defer([ctx]() { EVP_CIPHER_CTX_free(ctx); });

    // 初始化加密操作，使用SM4-ECB模式
    if(1 != EVP_EncryptInit_ex(ctx, EVP_sm4_ecb(), NULL, key.data(), NULL)) {
        sl::loger::error("Failed to initialize SM4-ECB encryption");
        return {};
    }
    EVP_CIPHER_CTX_set_padding(ctx, EVP_PADDING_PKCS7);

    // 计算输出缓冲区大小（输入长度+块大小）
    std::vector<sl::byte> out(
        data.size() + EVP_CIPHER_block_size(EVP_sm4_ecb()));
    int out_len = 0;
    int tmp_len = 0;

    // 执行加密
    if(1 != EVP_EncryptUpdate(
                ctx, out.data(), &out_len, data.data(), data.size())) {
        sl::loger::error("Failed to perform SM4-ECB encryption");
        return {};
    }

    // 完成加密操作
    if(1 != EVP_EncryptFinal_ex(ctx, out.data() + out_len, &tmp_len)) {
        sl::loger::error("Failed to finalize SM4-ECB encryption");
        return {};
    }

    out_len += tmp_len;
    out.resize(out_len);
    return out;
}

std::vector<sl::byte> sl::sym_decrypt(
    const std::vector<byte>& data, const std::vector<byte>& key)
{
    // 检查密钥长度是否为16字节（SM4要求）
    if(key.size() != 16) {
        sl::loger::error("SM4 key must be 16 bytes");
        return {};
    }

    // SM4-ECB要求输入数据长度是16字节的倍数
    if(data.size() % 16 != 0) {
        sl::loger::error(
            "SM4-ECB encrypted data length must be multiple of 16 bytes");
        return {};
    }

    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
    if(!ctx) {
        sl::loger::error("Failed to create EVP_CIPHER_CTX");
        return {};
    }
    defer([ctx]() { EVP_CIPHER_CTX_free(ctx); });

    // 初始化解密操作，使用SM4-ECB模式
    if(1 != EVP_DecryptInit_ex(ctx, EVP_sm4_ecb(), NULL, key.data(), NULL)) {
        sl::loger::error("Failed to initialize SM4-ECB decryption");
        return {};
    }
    EVP_CIPHER_CTX_set_padding(ctx, EVP_PADDING_PKCS7);

    // 计算输出缓冲区大小
    std::vector<sl::byte> out(data.size());
    int                   out_len = 0;
    int                   tmp_len = 0;

    // 执行解密
    if(1 != EVP_DecryptUpdate(
                ctx, out.data(), &out_len, data.data(), data.size())) {
        sl::loger::error("Failed to perform SM4-ECB decryption");
        return {};
    }

    // 完成解密操作
    if(1 != EVP_DecryptFinal_ex(ctx, out.data() + out_len, &tmp_len)) {
        sl::loger::error("Failed to finalize SM4-ECB decryption");
        return {};
    }

    out_len += tmp_len;
    out.resize(out_len);
    return out;
}